#region Using Statements
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
#endregion

namespace MegaEngine.Source.Sprites
{
    class TetrisPiece
    {
        TetrisBrick[,] brickMatrix;
        int fallingSpeed = 10;
        bool leftPressed;
        bool rightPressed;
        bool rotatePressed;
        public int pieceId;
        public int xOffset = 0;
        public float yOffset = 0;
        private Random random = new Random();
        private TetrisBrick brick0;
        private TetrisBrick brick1;
        private TetrisBrick brick2;
        private TetrisBrick brick3;
        private long leftMovementTimer;
        private long rightMovementTimer;
        public TetrisPiece(Texture2D theTexture, int speed)
        {
            fallingSpeed = speed;
            brick0 = new TetrisBrick();
            brick1 = new TetrisBrick();
            brick2 = new TetrisBrick();
            brick3 = new TetrisBrick();
            brick0.texture = theTexture;
            brick1.texture = theTexture;
            brick2.texture = theTexture;
            brick3.texture = theTexture;

            pieceId = getRandomPieceID();
            brickMatrix = new TetrisBrick[5, 5];
            initializePiece();
        }
        public TetrisPiece(Texture2D theTexture, int speed, int id)
        {
            fallingSpeed = speed;
            brick0 = new TetrisBrick();
            brick1 = new TetrisBrick();
            brick2 = new TetrisBrick();
            brick3 = new TetrisBrick();
            brick0.texture = theTexture;
            brick1.texture = theTexture;
            brick2.texture = theTexture;
            brick3.texture = theTexture;

            pieceId = id;
            brickMatrix = new TetrisBrick[5, 5];
            initializePiece();
        }
        public int update(float xOrigin, float yOrigin, int width, int height, GameTime gameTime, ArrayList environment, Vector2 theOrigin)
        {
            int result = 0;
            leftMovementTimer += gameTime.ElapsedGameTime.Milliseconds;
            rightMovementTimer += gameTime.ElapsedGameTime.Milliseconds;
            if (leftMovementTimer > 100)
            {
                leftMovementTimer = 0;
            }
            if (rightMovementTimer > 100)
            {
                rightMovementTimer = 0;
            }
            processInput(environment);
            setSpritePositions();
            float yMovement = (fallingSpeed * (float)gameTime.ElapsedGameTime.TotalSeconds);
            yOffset += yMovement;
            setSpritePositions();
            if (detectCollisions(environment))
            {
                yOffset = (int)yOffset;
                result = 1;
            }
            while (detectCollisions(environment))
            {
                yOffset--;
                setSpritePositions();
            }
            return result;
        }
        
        public void initializePiece()
        {
            xOffset = 9 * 32;
            yOffset = -96;
            brickMatrix[2,2] = brick1;
            if (pieceId == 0) // line
            {
                brickMatrix[2, 3] = brick0;
                brickMatrix[2, 1] = brick2;
                brickMatrix[2, 0] = brick3;
                setPieceColor(Color.Red);
            }
            else if (pieceId == 1) // square
            {
                brickMatrix[1, 2] = brick0;
                brickMatrix[2, 1] = brick2;
                brickMatrix[1, 1] = brick3;
                setPieceColor(Color.Blue);
            }
            else if (pieceId == 2) // T
            {
                brickMatrix[2, 1] = brick0;
                brickMatrix[2, 3] = brick2;
                brickMatrix[1, 2] = brick3;
                setPieceColor(Color.Yellow);
            }
            else if (pieceId == 3)// left L 
            { 
                brickMatrix[2, 1] = brick0;
                brickMatrix[2, 3] = brick2;
                brickMatrix[1, 1] = brick3;
                setPieceColor(Color.Orange);
            }
            else if (pieceId == 4) // right L
            {
                brickMatrix[2, 1] = brick0;
                brickMatrix[2, 3] = brick2;
                brickMatrix[1, 3] = brick3;
                setPieceColor(Color.Green);
            }
            else if (pieceId == 5) // left S
            {
                brickMatrix[1, 1] = brick0;
                brickMatrix[2, 3] = brick2;
                brickMatrix[1, 2] = brick3;
                setPieceColor(Color.Purple);
            }
            else if (pieceId == 6) // right S
            {
                brickMatrix[2, 1] = brick0;
                brickMatrix[1, 3] = brick2;
                brickMatrix[1, 2] = brick3;
                setPieceColor(Color.CornflowerBlue);
            }
            
        }

        private void setPieceColor(Color c)
        {
            foreach (Sprite s in brickMatrix)
            {
                if (s != null)
                {
                    s.color = c;
                }
            }
        }

        public ArrayList getSprites()
        {
            ArrayList result = new ArrayList();
            foreach(Sprite s in brickMatrix)
            {
                if (s != null)
                {
                    result.Add(s);
                }
            }
            return result;
        }
        public void setSpritePositions()
        {
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    if (brickMatrix[i, j] != null)
                    {
                        brickMatrix[i, j].levelOrigin.X = i * 32 + xOffset;
                        brickMatrix[i, j].levelOrigin.Y = j * 32 + yOffset;
                    }
                }
            }
        }
        public void setDisplayNext()
        {
            yOffset = 50;
            xOffset = 640;
        }
        private void processInput(ArrayList environment)
        {
            KeyboardState keyboard = Keyboard.GetState();
            GamePadState gamepad = GamePad.GetState(PlayerIndex.One);
            if ((keyboard.IsKeyDown(Keys.Left) || gamepad.ThumbSticks.Left.X < -.5) && (leftPressed == false || leftMovementTimer == 0))
            {
                if (leftPressed == false)
                {
                    leftMovementTimer = -50;
                }
                leftPressed = true;
                xOffset -= 32;
                setSpritePositions();
                if (detectCollisions(environment))
                {
                    xOffset += 32;
                    setSpritePositions();
                }
            }
            else if ( (keyboard.IsKeyDown(Keys.Right) || gamepad.ThumbSticks.Left.X > .5) && (rightPressed == false || rightMovementTimer == 0))
            {
                if (rightPressed == false)
                {
                    rightMovementTimer = -50;
                }
                rightPressed = true;
                xOffset += 32;
                setSpritePositions();
                if (detectCollisions(environment))
                {
                    xOffset -= 32;
                    setSpritePositions();
                }
            }
            if (keyboard.IsKeyDown(Keys.Down) || gamepad.ThumbSticks.Left.Y < -.5)
            {
                yOffset += 10;
                setSpritePositions();
                while (detectCollisions(environment))
                {
                    yOffset --;
                    setSpritePositions();
                }
                
            }
            if ( (keyboard.IsKeyDown(Keys.Z) || gamepad.Buttons.A == ButtonState.Pressed) && rotatePressed == false)
            {
                rotatePressed = true;
                rotateMatrixCounterClockwise();
                setSpritePositions();
                if (detectCollisions(environment))
                {
                    rotateMatrixClockwise();
                    setSpritePositions();
                }
            }
            else if ( (keyboard.IsKeyDown(Keys.X) || gamepad.Buttons.B == ButtonState.Pressed) && rotatePressed == false)
            {
                rotatePressed = true;
                rotateMatrixClockwise();
                setSpritePositions();
                if (detectCollisions(environment))
                {
                    rotateMatrixCounterClockwise();
                    setSpritePositions();
                }
            }

            if (keyboard.IsKeyUp(Keys.X) && keyboard.IsKeyUp(Keys.Z) && gamepad.Buttons.B == ButtonState.Released && gamepad.Buttons.A == ButtonState.Released)
            {
                rotatePressed = false;
            }

            if(keyboard.IsKeyUp(Keys.Left) && gamepad.ThumbSticks.Left.X == 0){
                leftPressed = false;
            }
            if(keyboard.IsKeyUp(Keys.Right) && gamepad.ThumbSticks.Left.X == 0){
                rightPressed = false;
            }
        }
        private bool detectCollisions(ArrayList environment)
        {
            Vector2 movement = new Vector2();
            movement.Y = 1;
            foreach (Sprite s in brickMatrix)
            {
                if (s != null)
                {
                    Sprite c = s.detectCollisions(environment);
                    if (c!=null)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        private void rotateMatrixCounterClockwise()
        {
            TetrisBrick[,] n = new TetrisBrick[5, 5];
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    n[4 - i, j] = brickMatrix[j, i];
                }
            }
            brickMatrix = n;
        }
        private void rotateMatrixClockwise()
        {
            TetrisBrick[,] n = new TetrisBrick[5, 5];
            for (int i = 0; i < 5; i++)
            {
                for (int j = 0; j < 5; j++)
                {
                    n[i, 4-j] = brickMatrix[j, i];
                }
            }
            brickMatrix = n;
        }
        private int getRandomPieceID()
        {
            int r = random.Next(0, 7);
            return r;
        }
    }
}
